package com.cloud.gatewaySpringSecurity.utils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author zhozixiong
 * @date 2022/7/19
 */
public class RsaUtil {
    /**
     * key的最小值
     */
    private static final int DEFAULT_KEY_SIZE = 2048;

    private RsaUtil() {
    }

    private static byte[] readFile(String fileName) throws Exception {//读取文件数据
        return Files.readAllBytes(new File(fileName).toPath());
    }

    private static PublicKey getPublicKey(byte[] bytes) throws Exception {//解析出公钥
        bytes = Base64.getDecoder().decode(bytes);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePublic(spec);
    }

    private static PrivateKey getPrivateKey(byte[] bytes) throws Exception {//解析出私钥
        bytes = Base64.getDecoder().decode(bytes);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePrivate(spec);
    }

    public static PublicKey getPublicKey(String fileName) throws Exception {
        byte[] bytes = readFile(fileName);
        return getPublicKey(bytes);
    }

    public static PrivateKey getPrivateKey(String fileName) throws Exception {
        byte[] bytes = readFile(fileName);
        return getPrivateKey(bytes);
    }

    /**
     * exists:判断文件是否存在
     * isDirectory:判断目录是否存在
     * mkdir:自能用来创建文件夹,且只能创建一级目录.如果上级不存在,就会创建失败
     * mkdirs:自能用来创建文件夹,且能创建多级目录.如果上级不存在,就会自动创建
     * createNewFile:自能用来创建文件,且只能在已存在的目录下创建文件,否则会创建失败
     *
     * @param filePath 文件路径
     * @param bytes    要写入文件的数据
     */
    private static void writeFile(String filePath, byte[] bytes) throws IOException {
        File file = new File(filePath);
        //没有此文件就新建
        if (!file.exists()) {
            file.createNewFile();
        }
        //将数据写入文件
        Files.write(file.toPath(), bytes);
    }//将钥匙写入相应的文件

    public static void generateKey(String pubKeyFileName, String priKeyFileName, String secret, int keySize) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(Math.max(keySize, DEFAULT_KEY_SIZE), secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        //生成公钥并写出
        byte[] pubKeyBytes = keyPair.getPublic().getEncoded();
        pubKeyBytes = Base64.getEncoder().encode(pubKeyBytes);
        writeFile(pubKeyFileName, pubKeyBytes);
        //生成私钥并写出
        byte[] priKeyBytes = keyPair.getPrivate().getEncoded();
        priKeyBytes = Base64.getEncoder().encode(priKeyBytes);
        writeFile(priKeyFileName, priKeyBytes);
    }//生成公钥和私钥，并写入文件
}
